package com.kxn.multi.module.service.service.impl;

import com.kxn.multi.module.security.util.JwtTokenUtil;
import com.kxn.multi.module.service.dto.security.ApiUserDetails;
import com.kxn.multi.module.service.dto.api.user.UserLoginDto;
import com.kxn.multi.module.service.dto.api.user.UserLoginReq;
import com.kxn.multi.module.service.dto.api.user.UserRegisterDto;
import com.kxn.multi.module.service.dto.api.user.UserRegisterReq;
import com.kxn.multi.module.service.entity.User;
import com.kxn.multi.module.service.mapper.UserMapper;
import com.kxn.multi.module.service.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.kxn.multi.module.service.util.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.kxn.multi.module.common.exception.ServiceException;

import javax.annotation.Resource;

/**
* <p>
* 用户表 服务实现类
* </p>
*
* @author kxn
* @since 2023-04-06
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private PageUtil pageUtil;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    JwtTokenUtil jwtTokenUtil;

    /**
    * 用户表分页列表
    * @param param 根据需要进行传值
    * @return
    */
    @Override
    public IPage<User> page(User param) {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
        // 账号
                .eq(!StringUtils.isEmpty(param.getUsername()), User::getUsername, param.getUsername())
            // 密码
                .eq(!StringUtils.isEmpty(param.getPassword()), User::getPassword, param.getPassword())
            // 用户名
                .eq(!StringUtils.isEmpty(param.getName()), User::getName, param.getName())
            // 手机号
                .eq(!StringUtils.isEmpty(param.getPhone()), User::getPhone, param.getPhone())
    ;

        IPage<User> page = page(pageUtil.page(), queryWrapper);
        return page;
    }

    /**
    * 用户表详情
    * @param id
    * @return
    */
    @Override
    public User detail(Long id) {
        return getById(id);
    }

    /**
    * 用户表新增
    * @param param 根据需要进行传值
    * @return
    */
    @Override
    public void create(User param) {
        if (!save(param)) {
            throw new ServiceException("添加数据失败");
        }
    }

    /**
    * 用户表修改
    * @param param 根据需要进行传值
    * @return
    */
    @Override
    public void update(User param) {
        if (!updateById(param)) {
            throw new ServiceException("更新数据失败");
        }
    }

    /**
    * 用户表修改
    * @param id 主键id
    * @param param 根据需要进行传值
    * @return
    */
    @Override
    public void updateById(Long id, User param) {
        User data = this.detail(id);
        if (data == null) {
            throw new ServiceException("数据不存在");
        }
        param.setId(id);
        update(param);
    }

    /**
    * 用户表删除(单个条目)
    * @param id
    * @return
    */
    @Override
    public void delete(Long id) {
        removeById(id);
    }

    /**
    * 用户表删除(多个条目)
    * @param ids
    * @return
    */
    @Override
    public void batchDelete(List<Long> ids) {
        removeByIds(ids);
    }


    /**
     * springsecurity 用户信息使用
     *
     * @param username
     * @return
     */
    @Override
    public UserDetails loadUserByUsername(String username) {
        User userInfo = getUserByUsername(username);
        if (userInfo != null) {
            return new ApiUserDetails(userInfo);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    /**
     * 根据用户名查找用户
     *
     * @param username
     * @return
     */
    @Override
    public User getUserByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User userInfo = this.getOne(wrapper);
        return userInfo;
    }

    /**
     * 根据手机号查找用户
     *
     * @param phone
     * @return
     */
    @Override
    public User getUserByPhone(String phone) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", phone);
        User userInfo = this.getOne(wrapper);
        return userInfo;
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    @Override
    public String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

    /**
     * 生成token
     *
     * @param user
     * @return
     */
    @Override
    public String generateToken(User user) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put(JwtTokenUtil.CLAIM_KEY_USERNAME, user.getUsername());
        claims.put(JwtTokenUtil.CLAIM_KEY_CREATED, new Date());
        String token = jwtTokenUtil.createToken(claims);
        return token;
    }

    /**
     * 注册用户
     *
     * @param userRegisterReq
     * @return
     */
    @Override
    public UserRegisterDto register(UserRegisterReq userRegisterReq) {
        String username = userRegisterReq.getUsername();
        String phone = userRegisterReq.getPhone();

        if (getUserByUsername(username) != null) {
            throw new ServiceException("用户名已存在");
        }
        if (getUserByPhone(phone) != null) {
            throw new ServiceException("手机号已被注册");
        }

        String password = this.encodePassword(userRegisterReq.getPassword());

        User userInfo = new User();
        userInfo.setUsername(username);
        userInfo.setPassword(password);
        userInfo.setPhone(phone);
        this.save(userInfo);

        String token = this.generateToken(userInfo);
        UserRegisterDto userRegisterDto = new UserRegisterDto();
        userRegisterDto.setUserId(userInfo.getId());
        userRegisterDto.setUsername(userInfo.getUsername());
        userRegisterDto.setToken(token);
        return userRegisterDto;
    }

    @Override
    public UserLoginDto login(UserLoginReq userLoginReq) {
        User user = getUserByUsername(userLoginReq.getUsername());
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        boolean isPasswordMatch = this.isPasswordMatch(userLoginReq.getPassword(), user.getPassword());
        if (!isPasswordMatch) {
            throw new ServiceException("密码错误");
        }

        String token = this.generateToken(user);
        UserLoginDto userLoginDto = new UserLoginDto();
        userLoginDto.setUserId(user.getId());
        userLoginDto.setUsername(user.getUsername());
        userLoginDto.setToken(token);
        return userLoginDto;
    }
}
